package com.handinfo.android.game;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import android.graphics.Point;

import com.handinfo.android.DWGameManager;
import com.handinfo.android.core.graphics.DWGraphics;
import com.handinfo.android.core.object.Actor;
import com.handinfo.android.core.object.Scene;
import com.handinfo.android.core.resource.Resource;
import com.handinfo.android.game.skill.CombatSkill;
import com.handinfo.android.utils.MathConstants;
import com.handinfo.android.utils.Tools;

public class GameActor extends Actor implements IActorAttribute
{
	//最后一次同步坐标时的坐标信息
	public int m_lastPosX;
	public int m_lastPosY;
	
	public int m_hp, m_hpMax;
	public int m_mp, m_mpMax;
	public long m_zhanli;
	
	public int[] m_attributes = new int[Attribute.SIZE];

	public byte m_type = 0;// NPC=0, 怪=1, 角色=2
	public byte m_direct = 0;
	public byte m_directBefore = 0;
	
	public int m_actor_flag;

	public String m_name = null;// 该角色的名字
	public byte m_sex = 0;// 该角色的性别
	public int m_faction = 0;// 该角色从属于哪个阵营
	public int m_vocation = 0;// 该角色的职业
	public int m_lv = 0;// 该角色的等级
	
	
	
	public boolean m_combating = false; // 是否在战斗中
	public String m_location = null;// 角色最后下线的场景名称

	/** 角色状态 */
	public int m_status = 0;
	/** 角色行为 */
	public int m_action = 0;
	/** 受创半径 */
	public int m_underAttack_range = 0;

	public boolean m_needSendPath = false; // 是否需要发送行进拐点
	public ArrayList<Integer> m_pathPoint = new ArrayList<Integer>(); // 行进拐点

	/** 目标Actor */
	public GameActor m_targetActor; // 目标actor

	/** 方向 */
	public static final int DIRECT_E = 0;// 东
	public static final int DIRECT_S = 1;// 南
	public static final int DIRECT_W = 2;// 西
	public static final int DIRECT_N = 3;// 北
	public static final int DIRECT_NUM = 4;

	public static final int DIRECT_ES = 5;
	public static final int DIRECT_SW = 6;
	public static final int DIRECT_WN = 7;
	public static final int DIRECT_NE = 8;

	// 动作
	public static final int ACTION_STAND = 0;
	public static final int ACTION_MOVE = 1;
	


	// 阵营
	public static final int FACTION_1 = 1; // 阵营1
	public static final int FACTION_2 = 2; // 阵营2
	public static final int FACTION_FRIEND = 3; // 对所有都友善
	public static final int FACTION_ENEMY = 4; // 对所有都敌对

	public int m_head_state = 0;// NPC头上状态
	
	public long m_dead_time = 0;

	public CombatSkill m_curCombatSkill;
	public GameEffect m_castSrcEffect; // 施法者光效（一般用于需要持续显现的吟唱或者通道法术）

	public GameActor()
	{
		super();
		m_hp = m_hpMax = 1;
		m_mp = m_mpMax = 1;
	}

	public GameActor(Resource resource)
	{
		super(resource);
		m_hp = m_hpMax = 1;
		m_mp = m_mpMax = 1;
	}

	public void move(int direct)
	{
		switch (direct) {
			case DIRECT_E:
				m_flipX = false;
				setAction(ACTION_MOVE * DIRECT_NUM + direct, m_velocity, 0, true,
						false);
				break;
			case DIRECT_S:
				if (m_direct == DIRECT_W) {
					m_flipX = true;
				}
				setAction(ACTION_MOVE * DIRECT_NUM + direct, 0, m_velocity, true,
						false);
				break;
			case DIRECT_W:
				m_flipX = false;
				setAction(ACTION_MOVE * DIRECT_NUM + direct, -m_velocity, 0, true,
						false);
				break;
			case DIRECT_N:
				if (m_direct == DIRECT_W) {
					m_flipX = true;
				}
				setAction(ACTION_MOVE * DIRECT_NUM + direct, 0, -m_velocity, true,
						false);
				break;
			case DIRECT_ES:
				setAction(ACTION_MOVE * DIRECT_NUM + DIRECT_E, m_velocity * (float) MathConstants.sqrt2 / 2, m_velocity
						* (float) MathConstants.sqrt2 / 2, true,
						false);
				break;
			case DIRECT_SW:
				setAction(ACTION_MOVE * DIRECT_NUM + DIRECT_W, -m_velocity * (float) MathConstants.sqrt2 / 2,
						m_velocity * (float) MathConstants.sqrt2 / 2, true,
						false);
				break;
			case DIRECT_WN:
				m_flipX = true;
				setAction(ACTION_MOVE * DIRECT_NUM + DIRECT_N, -m_velocity * (float) MathConstants.sqrt2 / 2,
						-m_velocity * (float) MathConstants.sqrt2 / 2, true,
						false);
				break;
			case DIRECT_NE:
				m_flipX = false;
				setAction(ACTION_MOVE * DIRECT_NUM + DIRECT_N, m_velocity * (float) MathConstants.sqrt2 / 2,
						-m_velocity * (float) MathConstants.sqrt2 / 2, true,
						false);
				break;
		}
	}

	/**
	 * 根据传入的点 移动
	 * @param pointX
	 * @param pointY
	 */
	public void moveto(float pointX, float pointY)
	{

		float dx = pointX - m_posX;
		float dy = pointY - m_posY;

		float hypotenuse = (float) Math.sqrt(dx * dx + dy * dy);
		float vx = dx * m_velocity / hypotenuse;
		float vy = dy * m_velocity / hypotenuse;

		if (Math.abs(dx) <= Math.abs(vx)) {
			vx = dx;
		}
		if (Math.abs(dy) <= Math.abs(vy)) {
			vy = dy;
		}

		int action = ACTION_MOVE * DIRECT_NUM;

		double sinD = vy / m_velocity;

		int direct = -1;
		double PI = Math.PI;
		if (sinD >= Math.sin(-PI / 8) && sinD <= Math.sin(PI / 8) && vx > 0) {
			direct = DIRECT_E;
		}
		else if (sinD >= Math.sin(PI / 8) && sinD <= Math.sin(PI * 3 / 8) && vx > 0) {
			direct = DIRECT_ES;
		}
		else if (sinD >= Math.sin(PI * 3 / 8)) {
			direct = DIRECT_S;
		}
		else if (sinD >= Math.sin(PI * 7 / 8) && sinD <= Math.sin(PI * 5 / 8) && vx < 0) {
			direct = DIRECT_SW;
		}
		else if (sinD >= Math.sin(-PI * 7 / 8) && sinD <= Math.sin(PI * 7 / 8) && vx < 0) {
			direct = DIRECT_W;
		}
		else if (sinD >= Math.sin(-PI * 5 / 8) && sinD <= Math.sin(-PI * 7 / 8) && vx < 0) {
			direct = DIRECT_WN;
		}
		else if (sinD <= Math.sin(-PI * 5 / 8)) {
			direct = DIRECT_N;
		}
		else if (sinD >= Math.sin(-PI * 3 / 8) && sinD <= Math.sin(-PI / 8) && vx > 0) {
			direct = DIRECT_NE;
		}

		switch (direct) {
			case DIRECT_E:
				m_flipX = false;
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_S:
				if (vx < 0) {
					m_flipX = true;
				}
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_W:
				m_flipX = false;
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_N:
				if (vx < 0) {
					m_flipX = true;
				}
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_ES:
				m_flipX = false;
				setAction(action + DIRECT_E, vx, vy, true, false);
				break;
			case DIRECT_SW:
				m_flipX = false;
				setAction(action + DIRECT_W, vx, vy, true, false);
				break;
			case DIRECT_WN:
				m_flipX = true;
				setAction(action + DIRECT_N, vx, vy, true, false);
				break;
			case DIRECT_NE:
				m_flipX = false;
				setAction(action + DIRECT_N, vx, vy, true, false);
				break;
		}

	}

	public void move(float vx, float vy, float v)
	{
		int action = ACTION_MOVE * DIRECT_NUM;

		double sinD = vy / v;

		int direct = -1;
		double PI = Math.PI;
		if (sinD >= Math.sin(-PI / 8) && sinD <= Math.sin(PI / 8) && vx > 0) {
			direct = DIRECT_E;
		}
		else if (sinD >= Math.sin(PI / 8) && sinD <= Math.sin(PI * 3 / 8) && vx > 0) {
			direct = DIRECT_ES;
		}
		else if (sinD >= Math.sin(PI * 3 / 8)) {
			direct = DIRECT_S;
		}
		else if (sinD >= Math.sin(PI * 7 / 8) && sinD <= Math.sin(PI * 5 / 8) && vx < 0) {
			direct = DIRECT_SW;
		}
		else if (sinD >= Math.sin(-PI * 7 / 8) && sinD <= Math.sin(PI * 7 / 8) && vx < 0) {
			direct = DIRECT_W;
		}
		else if (sinD >= Math.sin(-PI * 5 / 8) && sinD <= Math.sin(-PI * 7 / 8) && vx < 0) {
			direct = DIRECT_WN;
		}
		else if (sinD <= Math.sin(-PI * 5 / 8)) {
			direct = DIRECT_N;
		}
		else if (sinD >= Math.sin(-PI * 3 / 8) && sinD <= Math.sin(-PI / 8) && vx > 0) {
			direct = DIRECT_NE;
		}

		switch (direct) {
			case DIRECT_E:
				m_flipX = false;
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_S:
				if (vx < 0) {
					m_flipX = true;
				}
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_W:
				m_flipX = false;
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_N:
				if (vx < 0) {
					m_flipX = true;
				}
				setAction(action + direct, vx, vy, true, false);
				break;
			case DIRECT_ES:
				m_flipX = false;
				setAction(action + DIRECT_E, vx, vy, true, false);
				break;
			case DIRECT_SW:
				m_flipX = false;
				setAction(action + DIRECT_W, vx, vy, true, false);
				break;
			case DIRECT_WN:
				m_flipX = true;
				setAction(action + DIRECT_E, vx, vy, true, false);
				break;
			case DIRECT_NE:
				m_flipX = false;
				setAction(action + DIRECT_E, vx, vy, true, false);
				break;
		}
	}

	public void stay(int direct)
	{
		setAction(ACTION_STAND * DIRECT_NUM + direct, 0, 0, true, false);
	}

	/**
	 * 设定元件动作
	 * 
	 * @param actionIDNext
	 * @param mustChange
	 */
	public void setAction(int actionIDNext, boolean mustChange)
	{
		try {
			if (m_anim == null) {
//				Tools.debugPrintln("GameActor setAction(): anim == null! " + "name: " + m_name);
				return;
			}
			if (m_anim.m_actions == null) {
				Tools.debugPrintln("GameActor setAction(): actions == null! " + "name: " + m_name);
				return;
			}
			m_directBefore = m_direct;
			if (!mustChange) {
				if (m_actionIDNow == actionIDNext) {
					return;
				}
			}
			if (m_actionIDNow != actionIDNext) {
				m_actionIDBefore = m_actionIDNow;
			}

			m_actionIDNow = actionIDNext;
			int direct = m_actionIDNow % 4;
			m_direct = (byte) direct;

			m_frameId = 0;
			if (m_actionIDNow < 0) {
					Tools.debugPrintln("GameActor setAction(): actionIDNow < 0 ! " + "name: " + m_name + "-- actionId: "
							+ m_actionIDNow);
			}
			else if (m_anim != null && m_anim.m_actions != null && m_actionIDNow < m_anim.m_actions.length) {
				if (m_anim.m_actions[m_actionIDNow].length != 0) {
					m_frameIndex = m_anim.m_actions[m_actionIDNow][0] & 0x03FF;
				}
				else {
					Tools.debugPrintln("GameActor setAction(): action has no frame! " + "name: " + m_name + "-- actionId: "
							+ m_actionIDNow);
				}
			}
			else if (m_anim != null) {
				Tools.debugPrintln("GameActor setAction(): actionIDNow >= length ! " + "name: " + m_name + "-- actionId: "
						+ m_actionIDNow);
				m_frameIndex = m_anim.m_actions[m_actionIDNow
						% m_anim.m_actions.length][0] & 0x03FF;
			}
			m_frameDuration = 0;
			m_actionOver = false;
		}
		catch (Exception ex) {
			Tools.debug(ex);
		}
	}

	/**
	 * 血量变化
	 * 
	 * @param hp
	 */
	public void hpChanged(int hp)
	{
		m_hp += hp;
		m_hp = Tools.limit(m_hp, 0, m_hpMax);
	}

	/**
	 * mp变化
	 * 
	 * @param mp
	 */
	public void mpChanged(int mp)
	{
		m_mp += mp;
		m_mp = Tools.limit(m_mp, 0, m_mpMax);
	}

	/**
	 * 死亡后的处理
	 */
	public void dealDead()
	{
		
	}
	
	public boolean isDead()
	{
		return false;
	}

	public CopyOnWriteArrayList<Point> m_flexBuffer = new CopyOnWriteArrayList<Point>();
	public static final short FLEX_INDEX_X = 0;// 拐点x
	public static final short FLEX_INDEX_Y = 1;// 拐点y
	public static final short FLEX_INDEX_COUNT = 2;// 总数

	public void addFlex(Point flex)
	{
		m_flexBuffer.add(flex);
//		synchronized (m_flexBuffer) {
//			if (m_flexBuffer.isEmpty()) {
//				m_flexBuffer.add(flex);
//			}
//			else if (!m_flexBuffer.get(m_flexBuffer.size() - 1).equals(flex)) {
//				m_flexBuffer.add(flex);
//			}
//		}
	}

	public void clearFlex()
	{
		m_flexBuffer.clear();
	}

	/**
	 * 同屏更新的移动效果
	 */
	public void updateMove()
	{
		if (m_scene == null)
			return;
		if (this != m_scene.m_controlledActor) {
			if (!m_flexBuffer.isEmpty()) {
				int size = m_flexBuffer.size();
				if (size > 3) {
					Point p = m_flexBuffer.get(size-1);
					m_posX = p.x;
					m_posY = p.y;
					m_flexBuffer.clear();
					return;
				}
					
				int dx;
				int dy;

				Point point = m_flexBuffer.get(0);
				dx = point.x - m_posX;
				dy = point.y - m_posY;
				int distance = 1;
				boolean flag = false;
				if(this instanceof Npc && m_type == GameActorConstants.ACTOR_TYPE_PET){
					flag = true;
					distance = GameActorConstants.PET_STOPFLEX_DISTANCE;
				}
				if (Math.abs(dx) <= distance && Math.abs(dy) <= distance) {
					if(flag){
						m_flexBuffer.clear();
						stay(m_direct);
						return;
					}else{						
						m_flexBuffer.remove(0);
						if (!m_flexBuffer.isEmpty()) {
							point = m_flexBuffer.get(0);
							dx = point.x - m_posX;
							dy = point.y - m_posY;
						}
						else {
							stay(m_direct);
							return;
						}
					}
				}
				
				if (Math.abs(dx) <= distance && Math.abs(dy) <= distance) {
					m_vX = 0;
					m_vY = 0;
					return;
				}
				
				float hypotenuse = (float) Math.sqrt(dx * dx + dy * dy);
				float vx = dx * m_velocity / hypotenuse;
				float vy = dy * m_velocity / hypotenuse;

				if (Math.abs(dx) <= Math.abs(vx)) {
					vx = dx;
				}
				if (Math.abs(dy) <= Math.abs(vy)) {
					vy = dy;
				}
				move(vx, vy, Math.min(m_velocity, hypotenuse));
			}
		}
	}

	// // 基础属性
	// ///////////////////////////////////////////////////////////

	public static final int SENDPATH_INTERVAL = 3;

	public void logic()
	{
		super.logic();
		if (m_needSendPath) {
			// 定时发送移动信息
			if (m_scene.m_sceneHandler.m_frameCounter % SENDPATH_INTERVAL == 0) {
				synPosition();
			}
		}
		if (m_curCombatSkill != null && m_curCombatSkill.isActive()) {
			m_curCombatSkill.logic();
		}
		else {
			updateMove();
			if (System.currentTimeMillis() - m_dead_time > 5000){
				dealDead();
			}
		}
	}

	public void draw(DWGraphics g, int camX, int camY)
	{
//		if (m_scene != null) {
//			if (this == ((Scene) m_scene).m_controlledActor.m_targetActor) {
//				Scene.s_targetFrame.m_posX = m_posX;
//				Scene.s_targetFrame.m_posY = m_posY;
//				Scene.s_targetFrame.draw(g, camX, camY);
//				Scene.s_targetFrame.nextFrame();
//			}
//		}
		super.draw(g, camX, camY);
	}

	public boolean checkTargetFriend(GameActor actor)
	{
//		Tools.debugPrintln("me : " + m_faction + " : " + actor.m_faction);
		if (actor.m_faction == FACTION_FRIEND) {
			return true;
		}
		else if (actor.m_faction == m_faction) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * 转向目标
	 * 
	 * @param target
	 */
	public void changeDirectToTarget(GameActor target)
	{
		if (target == null)
			return;
		if (target.m_posX < m_posX) {
			m_flipX = false;
			m_direct = DIRECT_W;
		}
		else {
			m_flipX = false;
			m_direct = DIRECT_E;
		}
//		if (target.m_posY < m_posY && target.m_posX < m_posX) {
//			m_flipX = true;
//			m_direct = DIRECT_N;
//		}
//		else if (target.m_posX < m_posX) {
//			m_flipX = false;
//			m_direct = DIRECT_W;
//		}
//		else if (target.m_posY < m_posY) {
//			m_flipX = false;
//			m_direct = DIRECT_N;
//		}
//		else {
//			m_flipX = false;
//			m_direct = DIRECT_E;
//		}
	}

	// ////////////////////////////////////////////////////////////
	// // buf相关
	public static final int BUF_MAX_NUM = 6; // buf或者debf的最大数目
	public static final int NO_BUF_FLAG = -1; // 无buf的标志
	public ConcurrentHashMap<Long, ActorBuffer> m_buf = new ConcurrentHashMap<Long, ActorBuffer>(); // buf
	public ConcurrentHashMap<Long, ActorBuffer> m_debuf = new ConcurrentHashMap<Long, ActorBuffer>(); // debuf
	
	public void clearBufAndDebuf() {
		if (m_buf != null) {
			m_buf.clear();
		}
		if (m_debuf != null) {
			m_debuf.clear();
		}
	}

	/**
	 * 查找buf和debuf
	 * @param id
	 */
	public ActorBuffer getBufByID(long id)
	{
		ActorBuffer buf = null;
		buf = m_buf.get(id);
		if (buf != null) {
			return buf;
		}
		buf = m_debuf.get(id);
		if (buf != null) {
			return buf;
		}
		return null;
	}

	/**
	 * 添加buf
	 * 
	 * @param id
	 * @param duration 持续时间
	 * @param damageOverall 总治疗
	 * @param damageFrequency 治疗次数
	 * @param damageInterval 治疗间隔
	 */
	public void addBuf(long id, short iconId, int duration)
	{
		ActorBuffer buf = new ActorBuffer();
		buf.init(this, ActorBuffer.TYPE_BUF, id, iconId, duration);
		m_buf.put(id, buf);
	}

	/**
	 * 移除buf
	 * 
	 * @param id
	 */
	public void removeBuf(long id)
	{
		m_buf.remove(id);
	}

	/**
	 * 添加debuf
	 * 
	 * @param id
	 * @param duration 持续时间
	 * @param damageOverall 总伤害
	 * @param damageFrequency 伤害次数
	 * @param damageInterval 伤害间隔
	 */
	public void addDebuf(long id, short iconId, int duration)
	{
		ActorBuffer debuf = new ActorBuffer();
		debuf.init(this, ActorBuffer.TYPE_DEBUF, id, iconId, duration);
		m_debuf.put(id, debuf);
	}

	/**
	 * 移除debuf
	 * 
	 * @param id
	 */
	public void removeDeBuf(long id)
	{
		m_debuf.remove(id);
	}
	
	////buff debuff
	//////////////////////////////////////////////////////////

	public void dispose()
	{
		super.dispose();
		m_name = null;
		if (m_pathPoint != null) {
			m_pathPoint.clear();
			m_pathPoint = null;
		}
//		if (m_targetDamage != null) {
//			m_targetDamage.removeAllElements();
//			m_targetDamage = null;
//		}
		if (m_flexBuffer != null) {
			m_flexBuffer.clear();
			m_flexBuffer = null;
		}
//		if (m_buf != null) {
//			m_buf.removeAllElements();
//			m_buf = null;
//		}
//		if (m_debuf != null) {
//			m_debuf.removeAllElements();
//			m_debuf = null;
//		}
		m_targetActor = null;
//		m_castSrcEffect = null;
//		m_castTgtEffect = null;
	}

	public void destroy()
	{
		super.destroy();
		m_name = null;
		if (m_pathPoint != null) {
			m_pathPoint.clear();
			m_pathPoint = null;
		}
//		if (m_targetDamage != null) {
//			m_targetDamage.removeAllElements();
//			m_targetDamage = null;
//		}
		if (m_flexBuffer != null) {
			m_flexBuffer.clear();
			m_flexBuffer = null;
		}
		if (m_buf != null) {
			m_buf.clear();
			m_buf = null;
		}
		if (m_debuf != null) {
			m_debuf.clear();
			m_debuf = null;
		}
		m_targetActor = null;
//		m_castSrcEffect = null;
//		m_castTgtEffect = null;
	}

	@Override
	public String toString()
	{
		return "GameActor [m_name=" + m_name + ", m_gameId=" + m_gameId + ", m_resHead=" + m_resHead + "]";
	}

	public void addAttr(int index, int value)
	{
		if (m_attributes == null || index >= m_attributes.length) 
			return;
		m_attributes[index] = value;
	}

	public void setAttr(int index, int value)
	{
		if (m_attributes == null || index >= m_attributes.length) 
			return;
		m_attributes[index] = value;
	}

	public int getAttr(int index)
	{
		if (m_attributes == null || index >= m_attributes.length) 
			return 0;
		return m_attributes[index];
	}

	public int getHp()
	{
		return m_hp;
	}

	public int getMp()
	{
		return m_mp;
	}
	
	
	/**
	 * 跟服务器同步坐标
	 */
	public void synPosition()
	{
		if (m_lastPosX == m_posX && m_lastPosY == m_posY)
			return;
		m_lastPosX = m_posX;
		m_lastPosY = m_posY;
		int info = m_posX | (m_posY << 16);
		m_pathPoint.clear();
		m_pathPoint.add(Integer.valueOf(info));
		DWGameManager.getInstance().getSendMessage().sendMove(m_pathPoint);
	}
}
